home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / dev / m2 / m2_part1.lha / modula / dice / dice.LHA / examples / doshan / main.c < prev    next >
C/C++ Source or Header  |  1991-04-15  |  7KB  |  325 lines

  1.  
  2. /*
  3.  *  MAIN.C
  4.  *
  5.  *  MAIN FOR DOS HANDLER TEST PROGRAM FOR DICE
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <exec/nodes.h>
  10. #include <exec/ports.h>
  11. #include <exec/memory.h>
  12. #include <dos/dos.h>
  13. #include <dos/dosextens.h>
  14. #include <dos/filehandler.h>
  15.                 /*  -mRR -DREGISTERED    */
  16. #ifdef REGISTERED
  17.  
  18. #include <clib/exec_protos.h>
  19. #define abs            /*  alib_protos screws up abs    */
  20. #include <clib/alib_protos.h>
  21.  
  22. #else                /*  otherwise ...    */
  23.  
  24. extern void *FindTask();
  25. extern void *GetMsg();
  26. extern void *FindName();
  27. extern void *AllocMem();
  28. extern void *RemHead();
  29.  
  30. #endif
  31.  
  32. #include <stdio.h>
  33. #include <stdarg.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36.  
  37. #define DOS_TRUE    -1
  38. #define DOS_FALSE   0
  39.  
  40. #define BTOC(bptr)  ((void *)((long)(bptr) << 2))
  41. #define CTOB(cptr)  ((BPTR)(((long)cptr) >> 2))
  42.  
  43. typedef struct DosPacket    DosPacket;
  44. typedef struct FileHandle   FileHandle;
  45. typedef struct DeviceNode   DeviceNode;
  46. typedef struct Process        Process;
  47. typedef struct Node        Node;
  48. typedef struct List        List;
  49. typedef struct MsgPort        MsgPort;
  50. typedef struct Message        Message;
  51.  
  52. typedef struct XHandle {
  53.     Node    xh_Node;
  54.     long    xh_XHLen;
  55.     long    xh_Refs;
  56.     long    xh_Flags;
  57.     List    xh_List;
  58. } XHandle;
  59.  
  60. #define XHF_EOF     0x0001
  61.  
  62. typedef struct XNode {
  63.     Node    xn_Node;
  64.     char    *xn_Buf;
  65.     long    xn_Offset;
  66.     long    xn_Length;
  67. } XNode;
  68.  
  69. void returnpacket(DosPacket *);
  70. void Initialize(void);
  71. void UnInitialize(void);
  72.  
  73.  
  74. List    HanList;
  75. DeviceNode *DevNode;
  76. MsgPort    *PktPort;
  77.  
  78. /*
  79.  *  Note that we use the _main entry point.  Also notice that we do not
  80.  *  need to open any libraries.. they are openned for us via DICE's
  81.  *  unique auto-library-open ability.
  82.  */
  83.  
  84. void
  85. _main()
  86. {
  87.     DosPacket  *packet;
  88.  
  89.     {
  90.     Process *proc = FindTask(NULL);
  91.     PktPort = &proc->pr_MsgPort;
  92.     }
  93.     NewList(&HanList);
  94.     Initialize();
  95.  
  96.     /*
  97.      *    Main Loop
  98.      */
  99.  
  100.     for (;;) {
  101.     {
  102.         Message *msg;
  103.  
  104.         while ((msg = GetMsg(PktPort)) == NULL)
  105.         Wait(1 << PktPort->mp_SigBit);
  106.         packet = (DosPacket *)msg->mn_Node.ln_Name;
  107.     }
  108.  
  109.     /*
  110.      *  default return value
  111.      */
  112.  
  113.     packet->dp_Res1 = DOS_TRUE;
  114.     packet->dp_Res2 = 0;
  115.  
  116.     /*
  117.      *  switch on packet
  118.      */
  119.  
  120.     switch(packet->dp_Type) {
  121.     case ACTION_DIE:        /*    ??? */
  122.         break;
  123.     case ACTION_FINDUPDATE:     /*    FileHandle,Lock,Name        Bool    */
  124.     case ACTION_FINDINPUT:        /*    FileHandle,Lock,Name        Bool    */
  125.     case ACTION_FINDOUTPUT:     /*    FileHandle,Lock,Name        Bool    */
  126.         {
  127.         FileHandle *fh = BTOC(packet->dp_Arg1);
  128.         XHandle *xh;
  129.  
  130.         {
  131.             unsigned char *base = BTOC(packet->dp_Arg3);
  132.             int len = *base;
  133.             char buf[128];
  134.  
  135.             if (len >= sizeof(buf))
  136.             len = sizeof(buf) - 1;
  137.  
  138.             strncpy(buf, base + 1, len);
  139.             buf[len] = 0;
  140.  
  141.             if ((xh = FindName(&HanList, buf)) == NULL) {
  142.             xh = AllocMem(sizeof(XHandle) + len + 1, MEMF_PUBLIC | MEMF_CLEAR);
  143.             xh->xh_XHLen = sizeof(XHandle) + len + 1;
  144.             xh->xh_Node.ln_Name = (char *)(xh + 1);
  145.             movmem(buf, xh->xh_Node.ln_Name, len + 1);
  146.             NewList(&xh->xh_List);
  147.             AddTail(&HanList, &xh->xh_Node);
  148.             }
  149.             ++xh->xh_Refs;
  150.         }
  151.         fh->fh_Arg1 = xh;
  152.         fh->fh_Port = (MsgPort *)DOS_TRUE;
  153.         }
  154.         break;
  155.     case ACTION_READ:        /*    FHArg1,CPTRBuffer,Length    ActLength    */
  156.         /*
  157.          *    reading is straightforward except for handling EOF ... we
  158.          *    must guarentee a return value of 0 (no bytes left) before
  159.          *    beginning to return EOFs (-1's).  If we return a negative
  160.          *    number right off programs like COPY will assume a failure
  161.          *    (if TEST: is the source) and delete the destination file
  162.          */
  163.  
  164.         {
  165.         XHandle *xh = (XHandle *)packet->dp_Arg1;
  166.         long bytes;
  167.  
  168.         packet->dp_Res1 = 0;
  169.         while ((bytes = packet->dp_Arg3 - packet->dp_Res1) > 0) {
  170.             XNode *xn = RemHead(&xh->xh_List);
  171.  
  172.             if (xn == NULL)
  173.             break;
  174.  
  175.             if (bytes > xn->xn_Length - xn->xn_Offset)
  176.             bytes = xn->xn_Length - xn->xn_Offset;
  177.             movmem(xn->xn_Buf + xn->xn_Offset, (char *)packet->dp_Arg2 + packet->dp_Res1, bytes);
  178.  
  179.             xn->xn_Offset += bytes;
  180.             packet->dp_Res1 += bytes;
  181.             if (xn->xn_Offset == xn->xn_Length) {
  182.             FreeMem(xn->xn_Buf, xn->xn_Length);
  183.             FreeMem(xn, sizeof(XNode));
  184.             } else {
  185.             AddHead(&xh->xh_List, &xn->xn_Node);
  186.             }
  187.         }
  188.         if (packet->dp_Res1 == 0 && GetHead(&xh->xh_List) == NULL) {
  189.             if (xh->xh_Flags & XHF_EOF)
  190.             packet->dp_Res1 = -1;    /*  EOF */
  191.             xh->xh_Flags |= XHF_EOF;
  192.         }
  193.         }
  194.         break;
  195.     case ACTION_WRITE:        /*    FHArg1,CPTRBuffer,Length    ActLength    */
  196.         {
  197.         XHandle *xh = (XHandle *)packet->dp_Arg1;
  198.         XNode *xn;
  199.         long bytes = packet->dp_Arg3;
  200.  
  201.         packet->dp_Res1 = -1;
  202.         if (xn = AllocMem(sizeof(XNode), MEMF_PUBLIC|MEMF_CLEAR)) {
  203.             if (xn->xn_Buf = AllocMem(bytes, MEMF_PUBLIC)) {
  204.             movmem((char *)packet->dp_Arg2, xn->xn_Buf, bytes);
  205.             xn->xn_Length = bytes;
  206.             packet->dp_Res1 = bytes;
  207.             AddTail(&xh->xh_List, &xn->xn_Node);
  208.             xh->xh_Flags &= ~XHF_EOF;
  209.             } else {
  210.             FreeMem(xn, sizeof(XNode));
  211.             packet->dp_Res2 = ERROR_NO_FREE_STORE;
  212.             }
  213.         } else {
  214.             packet->dp_Res2 = ERROR_NO_FREE_STORE;
  215.         }
  216.         }
  217.         break;
  218.     case ACTION_END:        /*    FHArg1                Bool:TRUE    */
  219.         {
  220.         XHandle *xh = (XHandle *)packet->dp_Arg1;
  221.  
  222.         if (--xh->xh_Refs == 0 && GetHead(&xh->xh_List) == NULL) {
  223.             Remove(&xh->xh_Node);
  224.             FreeMem(xh, xh->xh_XHLen);
  225.         }
  226.         break;
  227.         }
  228.         break;
  229.     default:
  230.         packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
  231.         break;
  232.     }
  233.     if (packet) {
  234.         if (packet->dp_Res2)
  235.         packet->dp_Res1 = DOS_FALSE;
  236.         returnpacket(packet);
  237.     }
  238.     }
  239.  
  240.     /*
  241.      *    no reached
  242.      */
  243.  
  244.     UnInitialize();
  245.     _exit(0);
  246. }
  247.  
  248.  
  249. /*
  250.  *  PACKET ROUTINES.    Dos Packets are in a rather strange format as you
  251.  *  can see by this and how the PACKET structure is extracted in the
  252.  *  GetMsg() of the main routine.
  253.  */
  254.  
  255. void
  256. returnpacket(packet)
  257. DosPacket *packet;
  258. {
  259.     Message *mess;
  260.     MsgPort *replyPort;
  261.  
  262.     replyPort             = packet->dp_Port;
  263.     mess             = packet->dp_Link;
  264.     packet->dp_Port         = PktPort;
  265.     mess->mn_Node.ln_Name    = (char *)packet;
  266.     PutMsg(replyPort, mess);
  267. }
  268.  
  269. /*
  270.  *  During initialization DOS sends us a packet and sets our dn_SegList
  271.  *  pointer.  If we set our dn_Task pointer than every Open's go to the
  272.  *  same handler (this one).  If we set dn_Task to NULL, every Open()
  273.  *  will create a NEW instance of this process via the seglist, meaning
  274.  *  our process must be reentrant (i.e. -r option).
  275.  *
  276.  *  note: dn_Task points to the MESSAGE PORT portion of the process
  277.  *  (or your own custom message port).
  278.  *
  279.  *  If we clear the SegList then we also force DOS to reload our process
  280.  *  from disk, but we also need some way of then UnLoadSeg()ing it ourselves,
  281.  *  which we CANNOT do from this process since it rips our code out from
  282.  *  under us.
  283.  */
  284.  
  285. void
  286. Initialize()
  287. {
  288.     DeviceNode *dn;
  289.     Process *proc = FindTask(NULL);
  290.     DosPacket *packet;
  291.  
  292.     /*
  293.      *    Handle initial message.
  294.      */
  295.  
  296.     {
  297.     Message *msg;
  298.  
  299.     WaitPort(PktPort);
  300.     msg = GetMsg(PktPort);
  301.     packet = (DosPacket *)msg->mn_Node.ln_Name;
  302.     }
  303.  
  304.     {
  305.     DevNode = dn = BTOC(packet->dp_Arg3);
  306.  
  307.     dn->dn_Task = PktPort;
  308.     }
  309.     packet->dp_Res1 = DOS_TRUE;
  310.     packet->dp_Res2 = 0;
  311.     returnpacket(packet);
  312. }
  313.  
  314. void
  315. UnInitialize(void)
  316. {
  317.     {
  318.     DeviceNode *dn = DevNode;
  319.  
  320.     dn->dn_Task = NULL;
  321.     /* dn->dn_SegList = NULL; */
  322.     }
  323. }
  324.  
  325.